﻿// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable CommentTypo
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo
// ReSharper disable UnusedParameter.Local

/*
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

#endregion

#nullable enable

namespace AM.Reporting.Functions
{
    internal class NumToWordsFr : NumToWordsBase
    {
        private static Dictionary<string, CurrencyInfo> currencyList;

        private static string[] fixedWords =
        {
            "", "un", "deux", "trois", "quatre", "cinq", "six",
            "sept", "huit", "neuf", "dix", "onze",
            "douze", "treize", "quatorze", "quinze",
            "seize", "dix-sept", "dix-huit", "dix-neuf"
        };

        private static string[] fixedWords71to79 =
        {
            "soixante et onze", "soixante-douze", "soixante-treize", "soixante-quatorze",
            "soixante-quinze", "soixante-seize", "soixante-dix-sept", "soixante-dix-huit", "soixante-dix-neuf"
        };

        private static string[] fixedWords91to99 =
        {
            "quatre-vingt-onze", "quatre-vingt-douze", "quatre-vingt-treize", "quatre-vingt-quatorze",
            "quatre-vingt-quinze", "quatre-vingt-seize", "quatre-vingt-dix-sept", "quatre-vingt-dix-huit",
            "quatre-vingt-dix-neuf"
        };

        private static string[] tens =
        {
            "", "dix", "vingt", "trente", "quarante", "cinquante",
            "soixante", "soixante-dix", "quatre-vingt", "quatre-vingt-dix"
        };

        private static string[] hunds =
        {
            "", "cent", "deux cent", "trois cent", "quatre cent",
            "cinq cent", "six cent", "sept cent", "huit cent", "neuf cent"
        };

        private static WordInfo thousands = new WordInfo (false, "mille", "mille", "mille");
        private static WordInfo millions = new WordInfo (false, "million", "millions", "millions");
        private static WordInfo milliards = new WordInfo (false, "milliard", "milliards", "milliards");
        private static WordInfo trillions = new WordInfo (false, "billion", "billions", "billions");

        protected override string Str1000 (long value, WordInfo info, int counter)
        {
            var val = value % 1000;
            if (val == 0)
            {
                return "";
            }

            var r = new StringBuilder();

            // add hundred
            var hund = GetHund (info.male, val);
            if (hund != "")
            {
                r.Append (hund);
            }

            // decide whether to use the 100-10 separator or not
            var sep100_10 = Get100_10Separator();
            if (value < 1000 && hund == "")
            {
                sep100_10 = "";
            }

            val = val % 100;
            if (val < 20)
            {
                r.Append (sep100_10 + GetFixedWords (info.male, val));
            }
            else if (val is > 70 and < 80)
            {
                r.Append (sep100_10 + fixedWords71to79[val - 71]);
            }
            else if (val is > 90 and < 100)
            {
                r.Append (sep100_10 + fixedWords91to99[val - 91]);
            }
            else
            {
                // val is greater than fixed words count (usually 20), get tens separately
                var ten = GetTen (info.male, val / 10);
                var frac10 = GetFixedWords (info.male, val % 10);

                // decide whether to use 10-1 separator or not
                if (ten != "" && frac10 != "")
                {
                    var sep10_1 = "-";
                    if (val % 10 == 1)
                    {
                        if (val / 10 != 8)
                        {
                            sep10_1 = " et ";
                        }
                    }

                    r.Append (sep100_10 + ten + sep10_1 + frac10);
                }
                else if (ten != "")
                {
                    r.Append (sep100_10 + ten);
                }
                else if (frac10 != "")
                {
                    r.Append (sep100_10 + frac10);
                }
            }

            // special cases
            if (counter == 1) // the final
            {
                // 80 ends with 's' in case it's the final word
                if (val == 80)
                {
                    r.Append ("s");
                }

                // 100's ends with 's' in case it's the final word
                if (val == 0 && value % 1000 > 100)
                {
                    r.Append ("s");
                }
            }

            // add currency/group word
            r.Append (" ");
            r.Append (Case (value, info));

            // make the result starting with letter and ending with space
            if (r.Length != 0)
            {
                r.Append (" ");
            }

            return r.ToString().TrimStart (' ');
        }

        protected override string GetFixedWords (bool male, long value)
        {
            var result = fixedWords[value];
            if (!male)
            {
                if (value == 1)
                {
                    return "une";
                }
            }

            return result;
        }

        protected override string GetTen (bool male, long value)
        {
            return tens[value];
        }

        protected override string GetHund (bool male, long value)
        {
            return hunds[value / 100];
        }

        protected override WordInfo GetThousands()
        {
            return thousands;
        }

        protected override WordInfo GetMillions()
        {
            return millions;
        }

        protected override WordInfo GetMilliards()
        {
            return milliards;
        }

        protected override WordInfo GetTrillions()
        {
            return trillions;
        }

        protected override CurrencyInfo GetCurrency (string currencyName)
        {
            currencyName = currencyName.ToUpper();
            if (currencyName == "CAD")
            {
                currencyName = "USD";
            }

            return currencyList[currencyName];
        }

        protected override string GetZero()
        {
            return "zéro";
        }

        protected override string GetMinus()
        {
            return "moins";
        }

        protected override string GetDecimalSeparator()
        {
            return "et ";
        }

        static NumToWordsFr()
        {
            currencyList = new Dictionary<string, CurrencyInfo>();
            currencyList.Add ("USD", new CurrencyInfo (
                new WordInfo ("dollar", "dollars"),
                new WordInfo ("cent", "cents")));
            currencyList.Add ("EUR", new CurrencyInfo (
                new WordInfo ("euro", "euros"),
                new WordInfo ("cent", "cents")));
            currencyList.Add ("GBP", new CurrencyInfo (
                new WordInfo ("GBP", "GBP"),
                new WordInfo ("penny", "penny")));
        }
    }
}
